EC2 インスタンスのブロックデバイスの「終了時に削除」の情報を一覧取得し、一括で「はい」にする
コンバンハ、千葉(幸)です。
EC2 インスタンスの属性のひとつとして、ブロックデバイスマッピングの「終了時に削除(DeleteOnTermination
)」があります。
ここから確認できるものです。
この属性は、EC2 インスタンスにアタッチされた EBS ボリュームをインスタンスの終了(削除)時にあわせて削除するかどうかを定義しています。
デフォルトでは、ルートボリュームは true(あわせて削除される)、それ以外は false (ボリュームだけ残る)に設定されます。
今回は、「現状の設定を一覧で確認する」「すべてのインスタンスのブロックデバイスについて一括で true にする」コマンドを確認する機会がありましたのでその内容をご紹介します。
環境情報
mac OS と、AWS CloudShell で動作確認しています。
- macOS
- Ventura 13.4.1
- zsh
- jq 1.6
- AWS CLI 2.9.1
- AWS CloudShell
- bash
- Jq 1.5
- AWS CLI 2.12.2
インスタンスとそのブロックデバイスの情報を一括で確認する
いったん現状確認のため、このような形で情報をまとめたいと考えました。
- インスタンスごとに以下情報を取得する
- インスタンス ID
- インスタンス Name
- ブロックデバイスの情報
- デバイス名
DeleteOnTermination
- インスタンスごとに1行にまとめたい
- 各種情報はタブ区切りで出力する
- ブロックデバイスの情報はカンマ区切りで出力する
上記を満たすコマンド例は以下です。AWS CLI 以外に jq を必要とします。
aws ec2 describe-instances --output json\ | jq -r '.Reservations[].Instances[] | { InstanceId: .InstanceId, Name: (.Tags[] | select(.Key == "Name").Value), BlockDeviceMappings: [.BlockDeviceMappings[] | [.DeviceName, .Ebs.DeleteOnTermination | tostring] | join(",")]} | [.InstanceId, .Name, .BlockDeviceMappings[]] | join("\t")'
手元の検証環境で実行した際の例は以下の通り。
i-0f40748bd304c3148 Test-1 /dev/xvda,true /dev/sdb,false i-0a23ed292b5b0fb99 Test-2 /dev/xvda,true /dev/sdb,false /dev/sdf,false i-09d719edc7160ec1f Test-3 /dev/xvda,true /dev/sdb,false
出力をスプレッドシートに転記し、タブ区切りで列分割して多少手を加えれば冒頭の画像の状態になります。
コマンドはそこまで複雑なものではないですが、ポイントとしては以下のあたりです。
- [5行目]
DeleteOnTermination
の値 (boolean) をtostring
関数により文字列に変換- 環境によっては join 時にエラーになるため *1
- [5行目]
join
関数によりデバイス名とDeleteOnTermination
の値(を文字列にしたもの)をカンマ区切りで結合 - [7行目] インスタンス ID、インスタンス Name、ブロックデバイス情報をタブ区切りで結合
すべてのインスタンスのすべてのブロックデバイスを DeleteOnTermination = true にする
環境によって、どのボリュームがDeleteOnTermination = true
であるべきかはさまざまです。
あくまで今回は一律で変更する場合の手順確認の意図でコマンドを組み立てています。ここに載せているスクリプトを実行するとリージョン内のすべてのインスタンス・すべてのブロックデバイスが対象になりますので影響にご注意ください。
#!/bin/bash # 機能: EC2インスタンスの一覧を出力し、DeleteOnTerminationがfalseのブロックデバイスをtrueに変更します。 # EC2インスタンスの一覧を取得 instances=$(aws ec2 describe-instances --query "Reservations[].Instances[].InstanceId" --output text) # 各EC2インスタンスに対して処理を実行 for instance_id in $instances; do echo "Processing Instance: $instance_id" # BlockDeviceMappingsのうち、DeleteOnTerminationがfalseのDeviceNameを取得 device_mappings=$(aws ec2 describe-instances --instance-id "$instance_id" --query "Reservations[].Instances[].BlockDeviceMappings[?Ebs.DeleteOnTermination==\`false\`].DeviceName" --output text) # 各BlockDeviceMappingsに対して処理を実行 for device_name in $device_mappings; do echo " Updating Device: $device_name" # DeleteOnTerminationをtrueに変更 aws ec2 modify-instance-attribute --instance-id "$instance_id" --block-device-mappings "[{\"DeviceName\":\"$device_name\",\"Ebs\":{\"DeleteOnTermination\":true}}]" echo " Update Complete" done done echo "All instances processed"
updateinstances.sh
という名称でスクリプトを作成し、実行した場合の例は以下の通り。
$ sh updateinstances.sh Processing Instance: i-0f40748bd304c3148 Updating Device: /dev/sdb Update Complete Processing Instance: i-0a23ed292b5b0fb99 Updating Device: /dev/sdb Update Complete Updating Device: /dev/sdf Update Complete Processing Instance: i-09d719edc7160ec1f Updating Device: /dev/sdb Update Complete All instances processed
実行後に状態を確認すると、以下のようにすべてのブロックデバイスで true になっています。
$ aws ec2 describe-instances --output json\ | jq -r '.Reservations[].Instances[] | { InstanceId: .InstanceId, Name: (.Tags[] | select(.Key == "Name").Value), BlockDeviceMappings: [.BlockDeviceMappings[] | [.DeviceName, .Ebs.DeleteOnTermination | tostring] | join(",")]} | [.InstanceId, .Name, .BlockDeviceMappings[]] | join("\t")' i-0f40748bd304c3148 Test-1 /dev/xvda,true /dev/sdb,true i-0a23ed292b5b0fb99 Test-2 /dev/xvda,true /dev/sdb,true /dev/sdf,true i-09d719edc7160ec1f Test-3 /dev/xvda,true /dev/sdb,true
対象を限定したい場合には以下のようなカスマイズのパターンがあるでしょう。要件に応じて変更してください。
aws ec2 describe-instances
でフィルタリングする- 特定のタグがついているもの、など
instances
変数を直接指定するdevice_mappings
変数の値取得時に、特定のデバイス名は除外する
終わりに
EC2 インスタンスとそのブロックデバイスマッピングの情報を一括で取得したい、DeleteOnTermination を一括で true にしたい、という内容でした。
前者の「情報を一括で取得したい」については、階層が異なる情報に関してうまいこと1行にまとめる術が見つかって良かったです。jq を使わず--query
だけで実現できるとより良かったのですが、上手い書き方に辿り着けませんでした。
後者のスクリプトは ChatGPT の助けを借りて作成しました。以下の指示を与えるだけでほぼ完成形を出してくれたので、すごいなぁと感心してしまいました。
以下を満たすbashのスクリプトを作ってください。 - EC2インスタンスの一覧を出力 - EC2インスタンスごとに以下を実行 - BlockDeviceMappingsのうちDeleteOnTerminationがfalseのDeviceNameを取得 - aws ec2 modify-instance-attributeでDeleteOnTerminationをtrueに変更
どこかしら参考になれば幸いです。
以上、 チバユキ (@batchicchi) がお送りしました。
脚注
- tostringを省略した際に「jq: error (at <stdin>:467): string (",") and boolean (true) cannot be added」というエラーが出たことがありました。 ↩